[section .text]
[bits 64]

extern get_task_context
extern current
extern get_task_function
extern task_exit
extern inc_scheduling_times

global switch_task
switch_task:
    mov rdi, [current]
    call inc_scheduling_times
    cmp rax, 0
    jne .restore_task_context
    mov rdi, [current]
    call get_task_function
    sti
    call rax
.task_exit:
    mov rdi, [current]
    call task_exit
    ret

.restore_task_context:
    mov rdi, [current]
    call get_task_context
    ; rax + 8 * 0: rflags
    ; rax + 8 * 1: cs
    ; rax + 8 * 2: rip
    ; 以上3个寄存器是不能直接操作的，需要给它放到栈里面，然后ireq的时候会自动弹出来

    ; 暂时不回复rax，因为rax保存了context的地址，还需要用，我们在后面再回复rax
    ; mov rax, [rax + 8 * 2]
    mov rbx, [rax + 8 * 3]
    mov rcx, [rax + 8 * 4]
    mov rdx, [rax + 8 * 5]
    mov rdi, [rax + 8 * 6]
    mov rsi, [rax + 8 * 7]
    mov rbp, [rax + 8 * 8]
    mov rsp, [rax + 8 * 9]
    mov r8, [rax + 8 * 10]
    mov r9, [rax + 8 * 11]
    mov r10, [rax + 8 * 12]
    mov r11, [rax + 8 * 13]
    mov r12, [rax + 8 * 14]
    mov r13, [rax + 8 * 15]

.restore_rflags:
    push qword [rax + 8 * 0]
.restore_cs:
    push qword [rax + 8 * 18]
.restore_rip:
    push qword [rax + 8 * 1]
.restore_rax:
    ; 这次用完了，可以回复rax了
    mov rax, [rax + 8 * 2]
    iretq